package com.tools.common.io;

import com.tools.common.object.Note;

import java.io.*;

/**
 * 阻塞 IO 字节流拷贝操作包装类
 * */
@Note("阻塞 IO 字节流拷贝操作包装类")
public final class ByteIOCopyBean {

    @Note("源数据，字节输入流")
    private InputStream input;

    @Note("数据存放的目标，字节输出流")
    private OutputStream output;

    @Note("字节缓冲大小")
    private int bufferSize;

    /* *******************************************************************************************
     *
     *          构造器
     *
     * *******************************************************************************************
     * */

    public ByteIOCopyBean() {}

    public static ByteIOCopyBean of() {
        return new ByteIOCopyBean();
    }

    /* *******************************************************************************************
     *
     *          Getter / Setter
     *
     * *******************************************************************************************
     * */

    public InputStream getInput() {
        return input;
    }

    public BufferedInputStream getBufferedInput() {
        try {
            return (input instanceof BufferedInputStream)
                    ? (BufferedInputStream) input
                    : (bufferSize <= 0) ? new BufferedInputStream(input) : new BufferedInputStream(input, bufferSize);
        } catch (Throwable e){
            this.closeAll();
            throw e;
        }
    }

    public void setInput(InputStream inputStream) {
        if(inputStream == null) {
            this.closeAll();
            throw new NullPointerException();
        }
        this.input = inputStream;
    }

    public void setInput(File inFile) {
        try {
            if(inFile == null) throw new NullPointerException();
            this.input = IOKit.fileInputStream(inFile);
        } catch (Throwable e) {
            this.closeAll();
            throw e;
        }
    }

    public void setInput(String inPath) {
        try {
            if(inPath == null || inPath.isEmpty()) throw new NullPointerException();
            this.input = IOKit.fileInputStream(inPath);
        } catch (Throwable e) {
            this.closeAll();
            throw e;
        }
    }

    public OutputStream getOutput() {
        return output;
    }

    public OutputStream getBufferedOutput() {
        try {
            return (output instanceof BufferedOutputStream)
                    ? (BufferedOutputStream) output
                    : (bufferSize <= 0) ? new BufferedOutputStream(output) : new BufferedOutputStream(output, bufferSize);
        } catch (Throwable e) {
            this.closeAll();
            throw e;
        }
    }

    public void setOutput(OutputStream outputStream) {
        if(outputStream == null) {
            this.closeAll();
            throw new NullPointerException();
        }
        this.output = outputStream;
    }

    public void setOutput(File outFile) {
        this.setOutput(outFile, false);
    }

    public void setOutput(File outFile, boolean append) {
        try {
            if(outFile == null) throw new NullPointerException();
            this.output = IOKit.fileOutputStream(outFile, append);
        } catch (Throwable e) {
            this.closeAll();
            throw e;
        }
    }

    public void setOutput(String outPath) {
        this.setOutput(outPath, false);
    }

    public void setOutput(String outPath, boolean append) {
        try {
            if(outPath == null || outPath.isEmpty()) throw new NullPointerException();
            this.output = IOKit.fileOutputStream(outPath, append);
        } catch (Throwable e) {
            this.closeAll();
            throw e;
        }
    }

    public int getBufferSize() {
        return bufferSize;
    }

    public void setBufferSize(int bufferSize) {
        this.bufferSize = bufferSize;
    }

    @Override
    public String toString() {
        return "ByteIOCopyBean{" +
                "input=" + input +
                ", output=" + output +
                ", bufferSize=" + bufferSize +
                '}';
    }

    public boolean initInputChannel() {
        return input != null;
    }

    public boolean initOutputChannel() {
        return output != null;
    }

    public boolean enableCopy() {
        return input != null && output != null;
    }

    public int getBufferSizeOrReplace(int bufferSize) {
        return (this.bufferSize <= 0) ? bufferSize : this.bufferSize;
    }

    public void closeInput() {
        IOKit.close(input);
        input = null;
    }

    public void closeOutput() {
        IOKit.close(output);
        output = null;
    }

    public void closeAll() {
        closeInput();
        closeOutput();
    }

    public void copy() {
        IOKit.copy(this);
    }

    /* *******************************************************************************************
     *
     *          链式调用
     *
     * *******************************************************************************************
     * */

    public ByteIOCopyBean input(InputStream inputStream) {
        this.setInput(inputStream);
        return this;
    }

    public ByteIOCopyBean input(File inFile) {
        this.setInput(inFile);
        return this;
    }

    public ByteIOCopyBean input(String inPath) {
        this.setInput(inPath);
        return this;
    }

    public ByteIOCopyBean output(OutputStream output) {
        this.setOutput(output);
        return this;
    }

    public ByteIOCopyBean output(File outPath) {
        this.setOutput(outPath);
        return this;
    }

    public ByteIOCopyBean output(File outPath, boolean append) {
        this.setOutput(outPath, append);
        return this;
    }

    public ByteIOCopyBean output(String outPath) {
        this.setOutput(outPath);
        return this;
    }

    public ByteIOCopyBean output(String outPath, boolean append) {
        this.setOutput(outPath, append);
        return this;
    }

    public ByteIOCopyBean bufferSize(int bufferSize) {
        this.setBufferSize(bufferSize);
        return this;
    }
}
